package com.choosefine.paycenter.pay.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.choosefine.paycenter.account.dto.MainDto;
import com.choosefine.paycenter.account.dto.PaymentDto;
import com.choosefine.paycenter.account.model.AccountBill;
import com.choosefine.paycenter.account.service.AccountBillService;
import com.choosefine.paycenter.account.service.AccountService;
import com.choosefine.paycenter.common.enums.AccountBillStatus;
import com.choosefine.paycenter.common.enums.BizzSys;
import com.choosefine.paycenter.common.enums.FundFlow;
import com.choosefine.paycenter.common.enums.TradeType;
import com.choosefine.paycenter.common.utils.SerialNumberUtils;
import com.choosefine.paycenter.pay.api.RechargeService;
import com.choosefine.paycenter.pay.model.Channel;
import com.choosefine.paycenter.pay.model.Payment;
import com.choosefine.paycenter.pay.model.PaymentToTradeOrder;
import com.choosefine.paycenter.pay.service.*;
import com.choosefine.paycenter.pay.utils.PayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Comments：用于执行本地事物
 * Author：Jay Chang
 * Create Date：2017/5/10
 * Modified By：
 * Modified Date：
 * Why & What is modified：
 * Version：v1.0
 */
@Service
public class PayLocalTransactionServiceImpl implements PayLocalTransactionService{
    @Autowired
    private PaymentService paymentService;

    @Autowired
    private AccountBillService accountBillService;

    @Autowired
    private RechargeService rechargeService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private TradeOrderService tradeOrderService;

    @Autowired
    private ChannelService channelService;

    @Autowired
    private PaymentToTradeOrderService paymentToTradeOrderService;

    @Autowired
    private SerialNumberUtils serialNumberUtils;


    //这里认为支付单与账单是关系比较紧密的，故放在一个事务
    @Transactional
    public void processPaySuccess(JSONObject payOrderMessage){
        final String paySn = payOrderMessage.getString("sn");
        final BizzSys bizzSys = BizzSys.valueOf(payOrderMessage.getString("bizzSys"));

        final Payment payment = paymentService.findBizzSnAndBizzSysByPaySn(paySn);
        final String bizzSn = payment.getBizzSn();

        //执行更新支付单的支付状态为支付成功的本地事务
        paymentService.updatePaymentPaidSuccess(paySn);

        //如果是从账单发起的付款
        if(serialNumberUtils.isPayBizzSn(bizzSn)){
            PaymentToTradeOrder paymentToTradeOrder = paymentToTradeOrderService.findByPaySn(paySn);
            //更改账单状态(为完成)
            accountBillService.updateAccountBillSuccess(paymentToTradeOrder.getBizzSys(),paymentToTradeOrder.getOrderSn());
            //更改交易订单状态（为已支付）
            tradeOrderService.tradeOrderPaid(paymentToTradeOrder.getBizzSys().toString(),paymentToTradeOrder.getOrderSn());
        //如果是普通转账、或是分包款、批量发工资等
        }else{
            //同时更改账单(为完成)、交易订单状态（为已支付）
            JSONArray orders = payOrderMessage.getJSONArray("orders");
            if(null != orders && orders.size() > 0) {
                for (int i = 0 ; i < orders.size() ; i ++) {
                    JSONObject orderJSONObj = orders.getJSONObject(i);
                    String orderSn = orderJSONObj.getString("orderSn");
                    accountBillService.updateAccountBillSuccess(bizzSys,orderSn);
                    tradeOrderService.tradeOrderPaid(bizzSys.toString(),orderSn);
                }
            }
        }
        //账户余额处理
        PaymentDto paymentDto = PayUtils.getInstance().getPaymentDto(payOrderMessage);

        //主账户余额减少（只有余额来付款的时候，需要减少主账户余额）
        //若是余额支付的话需要减少主账户余额，增加对方账户余额,记录余额变更日志
        //TODO 若有其他需要减少主账户余额的支付方式，需要在里添加
        if ("SELF".equalsIgnoreCase(payOrderMessage.getString("channel")) && "BALANCE".equalsIgnoreCase(payOrderMessage.getString("payType"))) {
            accountService.decreaseMainAccountBalance(new MainDto(paymentDto.getAccountId(), paymentDto.getUserCode(), paymentDto.getAccountRealName(), paymentDto.getAmount()),paySn);
        }
        //对方账户余额增加
        accountService.increaseOppositeAccountBalance(paymentDto.getOrders(),paySn);
    }

    //这里认为支付单与账单是关系比较紧密的，故放在一个事务
    @Transactional
    public void processPayFailure(JSONObject payOrderMessage){
        final String paySn = payOrderMessage.getString("sn");
        final BizzSys bizzSys = BizzSys.valueOf(payOrderMessage.getString("bizzSys"));
        //执行更新支付单的支付状态为支付失败的本地事务
        paymentService.updatePaymentPaidFailure(paySn);
        //同时更改账单状态
        JSONArray orders = payOrderMessage.getJSONArray("orders");
        if(null != orders && orders.size() > 0) {
            for (int i = 0 ; i < orders.size() ; i ++) {
                JSONObject orderJSONObj = orders.getJSONObject(i);
                String orderSn = orderJSONObj.getString("orderSn");
                accountBillService.updateAccountBillFailure(bizzSys,orderSn);
            }
        }
    }

    //这里认为充值单与账单是关系比较紧密的，故放在一个事务
    @Transactional
    public void processRechargeSuccess(JSONObject payOrderMessage){
        final String rSn = payOrderMessage.getString("sn");
        final BizzSys bizzSys = BizzSys.valueOf(payOrderMessage.getString("bizzSys"));
        //执行更新支付单的支付状态为支付成功的本地事务
        rechargeService.rechargeComplted(rSn);
        //同时更改账单状态
        //accountBillService.updateAccountBillSuccess(bizzSys,rSn);
        //充值成功才记录账单
        AccountBill accountBill = getAccountBill(payOrderMessage);
        accountBillService.recordAccountBill(accountBill);
        //更新账单中充值使用的银行
        accountBillService.recordBankNameByBizzSysAndOrderSn(bizzSys,rSn,channelService.findChannelByChannelCode(payOrderMessage.getString("channel")).getBankName());
        //账户余额处理
        MainDto mainDto = new MainDto(payOrderMessage.getLong("accountId"),payOrderMessage.getString("userCode"),payOrderMessage.getString("realName"),payOrderMessage.getBigDecimal("amount"));
        //充值成功增加余额
        accountService.increaseMainAccountBalance(mainDto,rSn);
    }

    private AccountBill getAccountBill(JSONObject payOrderMessage) {
        AccountBill accountBill = new AccountBill();
        accountBill.setMainAccountId(payOrderMessage.getLong("accountId"));
        accountBill.setMainAccountUserCode(payOrderMessage.getString("userCode"));
        accountBill.setMainAccountMobile(payOrderMessage.getString("accountMobile"));
        accountBill.setMainAccountRealName(payOrderMessage.getString("realName"));
        accountBill.setAmount(payOrderMessage.getBigDecimal("amount"));
        Channel channel = channelService.findChannelByChannelCode(payOrderMessage.getString("channel"));
        accountBill.setImg(channel.getLogo());
        accountBill.setBizzSys(BizzSys.valueOf(payOrderMessage.getString("bizzSys")));
        accountBill.setTradeType(TradeType.RECHARGE);
        accountBill.setOperName(payOrderMessage.getString("operName"));
        accountBill.setStatus(AccountBillStatus.COMPLETE);
        accountBill.setBankName(channel.getBankName());
        accountBill.setFundFlow(FundFlow.IN);
        //充值的时候,账单的orderSn即为充值流水号
        accountBill.setOrderSn(payOrderMessage.getString("sn"));
        return accountBill;
    }

    //这里认为充值单与账单是关系比较紧密的，故放在一个事务
    @Transactional
    public void processRechargeFailure(JSONObject payOrderMessage){
        final String rSn = payOrderMessage.getString("sn");
        final BizzSys bizzSys = BizzSys.valueOf(payOrderMessage.getString("bizzSys"));
        //执行更新充值单的支付状态为支付失败的本地事务
        rechargeService.rechargeFailure(rSn);
        //同时更改账单状态
        accountBillService.updateAccountBillFailure(bizzSys,rSn);
    }
}
